#ifndef CSPLINE_H
#define CSPLINE_H

/**
 * The module implements an interface to gsl spline interpolators.
 * Data set is interpolated with a cubic spline with f''(x)=0, x=a,b
 * boundary conditions.
 */

#include "cdecl.h"
#include <gsl/gsl_interp.h>

/**
 * The structure defines an object to be shared between different 
 * trajectory_len instances to perform t -> l mapping task for curves,
 * for which it's impossible to calculate the mapping analytically.
 * The task is guaranteed not to modify it's internal states to be able
 * to run it in concurrent therads. 
 * Thus we can not use index accelerator, what would become more a 
 * problem, as number of knots increase.
 */
struct cspline {
	double * xx, * yy; // knots
	uint32_t N; // number of knots
	gsl_interp * interp;
	
	
	unsigned int refcnt; // Number of references to the object. The idea is like 
	// that, used by garbage collectors. We give a pointer to memory patch
	// with the object to everyone, who needs it, increasing this value 
	// every time. 
	// Later, if an object doesn't need this object any more, free is 
	// called, that decreases the refcnt. If refcnt becomes 0, malloc-free
	// is called in addition to internal structures deallocation
};



/**
 * Creates cspline object. Knot arrays xx and yy are
 * pointers to malloc-ed memory patches with data. After construction,
 * cspline becomes responsible for freeing these patches - if the user
 * has malloc-ed them, they shall be silently forgotten. If they were not
 * malloced, they may not be passed here (malloc and copy your data 
 * yourself, please).
 * If init fails, other init may be called after.
 * @param operation status - 0 if OK, error code otherwise:
 * 1 - Out of memory
 * 2 - gsl failed
 * @param xx - arguments array, such that \forall i > j: xx[i] > xx[j]
 * @param yy - values array
 * @param N array lengths
 * @return new object or NULL in case of error
 */
struct cspline * cspline_init(uint8_t * status, double * xx, double * yy, uint32_t N);


/**
 * Frees cspline object including malloc deallocation of the whole, 
 * if refcnt drops down to zero. Shall be called by every instance 
 * owning the object pointer.
 * @param cs - cspline object 
 */
void cspline_free(struct cspline * cs);

/**
 * Increases reference counter to identify that a reference to the
 * object has been copied to other holder.
 * @param cs - cspline object
 */
void cspline_notify_copied(struct cspline * cs);


/**
 * Calculates spline value at given point x.
 * @param x - point to calculate spline at
 * @param y - place to push answer to
 * @return 0 - OK, other statuses for error, returned gsl library 
 * function error status
 */
int cspline_calculate(const struct cspline * cs, double x, double * y);




#endif
